package com.qiaofang.applet.rest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qiaofang.applet.common.constant.ResponseCode;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.dto.DataRequest;
import com.qiaofang.applet.common.dto.DataResponse;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.applet.constants.SearchTypeConstants;
import com.qiaofang.applet.constants.UpDownFlagConstants;
import com.qiaofang.applet.service.other.domain.Corporation;
import com.qiaofang.applet.service.other.service.*;
import com.qiaofang.applet.service.other.service.dto.*;
import com.qiaofang.applet.service.property.domain.*;
import com.qiaofang.applet.service.property.service.*;
import com.qiaofang.applet.service.property.service.dto.*;
import com.qiaofang.applet.service.property.service.mapstruct.AreaMapper;
import com.qiaofang.applet.service.property.service.mapstruct.DistrictMapper;
import com.qiaofang.applet.service.property.service.mapstruct.EstateMapper;
import com.qiaofang.applet.service.property.service.mapstruct.FirsthandEstateMapper;
import com.qiaofang.common.response.DataResultResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/pcweb/common")
@Api(tags = "公共：公共接口")
public class CommonController {

    @Autowired
    CityCompanyService cityCompanyService;

    @Autowired
    DistrictService districtService;

    @Autowired
    AreaService areaService;

    @Autowired
    AreaMapper areaMapper;

    @Autowired
    DistrictMapper districtMapper;

    @Autowired
    FirsthandEstateMapper firsthandEstateMapper;

    @Autowired
    DictCorpService dictCorpService;

    @Autowired
    EstateService estateService;

    @Autowired
    ProvinceCityService provinceCityService;

    @Autowired
    PropertyService propertyService;

    @Autowired
    FirsthandEstateService firsthandEstateService;

    @Autowired
    EstateMapper estateMapper;

    @Autowired
    WxaQrCodeService wxaQrCodeService;

    @Autowired
    private ShortCodeService shortCodeService;

    @Autowired
    private CorporationService corporationService;

    @PostMapping("/getCityList")
    @ApiOperation(value = "城市列表", notes = "城市列表")
    public DataResponse<List<CityDesDto>> getCityList(HttpServletRequest request) {
        List<CityDesDto> datas = cityCompanyService.getCityList(QfContextHolder.getContext().getCorporationCode());
        log.info("获取城市列表,corporationCode:{},host:{},qfhost:{},cityList:{}",
                QfContextHolder.getContext().getCorporationCode(),
                request.getHeader("Host"),
                request.getHeader("qfhost"),
                JSON.toJSONString(datas));
        return DataResponse.ok(datas);
    }

    @PostMapping("/getDistrictList")
    @ApiOperation(value = "区域列表", notes = "区域列表")
    public DataResponse<List<DistrictDto>> getDistrictList() {
        List<District> districtList = districtService.findAllByCityCode(QfContextHolder.getContext().getCityCode());

        return DataResponse.ok(districtList.parallelStream().map(districtMapper::domainToDto).collect(Collectors.toList()));
    }

    @PostMapping("/getAreaList")
    @ApiOperation(value = "商圈列表", notes = "商圈列表")
    public DataResponse<List<AreaDto>> getAreaList(@RequestBody @Valid DataRequest<UuidDto> request) {
        List<Area> areaList = areaService.findAllByDistrictUuid(request.getParam().getUuid());

        return DataResponse.ok(areaList.parallelStream().map(areaMapper::domainToDto).collect(Collectors.toList()));
    }

    @PostMapping("/getDistrictAndArea")
    @ApiOperation(value = "城区商圈列表", notes = "城区商圈列表")
    public DataResponse<List<DistrictAreaDto>> getDistrictAndArea() {
        List<DistrictAreaDto> list = districtService.findAllDistrictAndArea(QfContextHolder.getContext().getCorporationCode(), QfContextHolder.getContext().getCityCode());
        return DataResponse.ok(list);
    }

    @PostMapping("/getDictList")
    @ApiOperation(value = "字典列表接口", notes = "字典列表接口")
    public DataResponse<Map<String, List<DictDto>>> getDictList(@RequestBody DataRequest<DictTypeDto> request) {
        Map<String, List<DictDto>> result = dictCorpService.getDictCollectionByType(request.getParam().getDictTypeSet(), QfContextHolder.getContext().getCorporationCode());
        return DataResponse.ok(result);
    }

    @PostMapping("/mainSearch")
    @ApiOperation(value = "首页搜索", notes = "首页搜索")
    public DataResponse<List<MainSearchDetailDTO>> mainSearch(@RequestBody @Valid DataRequest<MainSearchQueryDTO> request) {
        request.getParam().setCityCode(QfContextHolder.getContext().getCityCode());
        List<MainSearchDetailDTO> result = new ArrayList<>();

        if (SearchTypeConstants.FIRSTHAND_ESTATE.getValue().equals(request.getParam().getSearchType())) {
            FirsthandEstateQueryDto firsthandEstateQueryDto = new FirsthandEstateQueryDto();
            firsthandEstateQueryDto.setEstateName(request.getParam().getSearchName());
            firsthandEstateQueryDto.setCityCode(request.getParam().getCityCode());
            firsthandEstateQueryDto.setUpDownFlag(UpDownFlagConstants.UP_FLAG.getValue());

            List<FirsthandEstate> firsthandEstateList = firsthandEstateService.findAllByParams(firsthandEstateQueryDto);

            result = Optional.ofNullable(firsthandEstateList).orElseGet(Lists::newArrayList).stream().map(item -> {
                MainSearchDetailDTO dto = new MainSearchDetailDTO();
                dto.setEstateName(item.getEstateName());
                dto.setCityName(item.getCityName());
                dto.setAreaName(item.getAreaName());
                dto.setPropertyTypeList(firsthandEstateMapper.splitString(item.getPropertyType()));
                dto.setEstateUniqueUuid(item.getEstateUniqueUuid());
                return dto;
            }).collect(Collectors.toList());

        } else if (SearchTypeConstants.SALE_PROPERTY.getValue().equals(request.getParam().getSearchType())) {
            SalePropertyQueryDto salePropertyQueryDto = new SalePropertyQueryDto();
            salePropertyQueryDto.setEstateName(request.getParam().getSearchName());
            salePropertyQueryDto.setCityCode(request.getParam().getCityCode());
            salePropertyQueryDto.setUpDownFlag(UpDownFlagConstants.UP_FLAG.getValue());
            salePropertyQueryDto.setValidStatus(true);

            List<Property> salePropertyList = propertyService.findAllSaleByParams(salePropertyQueryDto);
            Map<String, List<Property>> estateMap = Optional.ofNullable(salePropertyList)
                    .orElseGet(Lists::newArrayList).stream().filter(item -> StringUtils.isNotBlank(item.getEstateUniqueUuid()))
                    .collect(Collectors.groupingBy(Property::getEstateUniqueUuid));

            if (estateMap != null) {
                for (String estateUniqueUuid : estateMap.keySet()) {
                    List<Property> propertyList = estateMap.get(estateUniqueUuid);
                    MainSearchDetailDTO dto = estateMapper.domainToDtailDto(propertyList.get(0));
                    dto.setSaleNum(propertyList.size());
                    result.add(dto);
                }
            }
        } else if (SearchTypeConstants.RENT_PROPERTY.getValue().equals(request.getParam().getSearchType())) {
            RentPropertyQueryDto rentPropertyQueryDto = new RentPropertyQueryDto();
            rentPropertyQueryDto.setEstateName(request.getParam().getSearchName());
            rentPropertyQueryDto.setCityCode(request.getParam().getCityCode());
            rentPropertyQueryDto.setUpDownFlag(UpDownFlagConstants.UP_FLAG.getValue());
            rentPropertyQueryDto.setValidStatus(true);

            List<Property> rentPropertyList = propertyService.findAllRentByParams(rentPropertyQueryDto);

            Map<String, List<Property>> estateMap = Optional.ofNullable(rentPropertyList)
                    .orElseGet(Lists::newArrayList).stream().filter(item -> StringUtils.isNotBlank(item.getEstateUniqueUuid()))
                    .collect(Collectors.groupingBy(Property::getEstateUniqueUuid));

            if (estateMap != null) {
                for (String estateUniqueUuid : estateMap.keySet()) {
                    List<Property> propertyList = estateMap.get(estateUniqueUuid);
                    MainSearchDetailDTO dto = estateMapper.domainToDtailDto(propertyList.get(0));
                    dto.setRentNum(propertyList.size());
                    result.add(dto);
                }
            }
        } else if (SearchTypeConstants.ESTATE.getValue().equals(request.getParam().getSearchType())) {
            EstateQueryDto estateQueryDto = new EstateQueryDto();
            estateQueryDto.setEstateName(request.getParam().getSearchName());
            estateQueryDto.setCityCode(StringUtils.defaultString(request.getParam().getCityCode(), QfContextHolder.getContext().getCityCode()));
            List<Estate> allEstateByParams = estateService.findAllEstateByParams(estateQueryDto);
            List<EstateListDto> estateListDtos = estateService.convertDomainToEstateListDto(allEstateByParams);
            result = Optional.ofNullable(estateListDtos).orElseGet(Lists::newArrayList).stream().map(item -> {
                MainSearchDetailDTO mainSearchDetailDTO = new MainSearchDetailDTO();
                mainSearchDetailDTO.setOldEstateUniqueUuid(item.getEstateUniqueUuid());
                mainSearchDetailDTO.setEstateName(item.getEstateName());
                mainSearchDetailDTO.setRentNum(item.getRentNum());
                mainSearchDetailDTO.setSaleNum(item.getSaleNum());
                return mainSearchDetailDTO;
            }).collect(Collectors.toList());
        }
        return DataResponse.ok(result);
    }


    @PostMapping("/getFirstCityList")
    @ApiOperation(value = "新房城市列表", notes = "新房城市列表")
    public DataResponse<List<CityDesDto>> getFirstCityList() {
        List<CityDesDto> firstHandCityAndArea = provinceCityService.getFirstHandCity(QfContextHolder.getContext().getCorporationCode());
        return DataResponse.ok(firstHandCityAndArea);
    }

    @PostMapping("/getFirstAreaList")
    @ApiOperation(value = "新房城市区域列表", notes = "新房城市区域列表")
    public DataResponse<List<DistrictDto>> getFirstAreaList(@RequestBody @Valid DataRequest<CityQueryDto> request) {
        if (StringUtils.isBlank(request.getParam().getCityCode())) {
            throw new BusinessException("请先选择城市");
        }
        List<DistrictDto> firstHandArea = provinceCityService.getFirstHandArea(request.getParam().getCityCode());
        return DataResponse.ok(firstHandArea);
    }

    @PostMapping("/getWxQRCode")
    @ApiOperation(value = "获取微信小程序码", notes = "获取微信小程序码")
    public DataResponse<String> getWxQRCode(@RequestBody DataRequest<WxaQrCodeDto> request) {
        log.info("getWxQRCode params: {}", JSONObject.toJSONString(request));
        String qrCode = wxaQrCodeService.createQrCode(request.getParam());
        return DataResponse.ok(qrCode);
    }

    @PostMapping("/getShortCode")
    @ApiOperation(value = "获取短码", notes = "获取短码")
    public DataResponse<List<String>> getShortCode(@RequestBody DataRequest<List<GetCodeDto>> request) {
        return DataResponse.ok(shortCodeService.getShortCodeList(request.getParam()));
    }

    @PostMapping("/getUniqueUuid")
    @ApiOperation(value = "获取唯一uuid", notes = "获取唯一uuid")
    public DataResponse<List<String>> getUniqueUuid(@RequestBody DataRequest<List<GetUniqueUuidDto>> request) {
        return DataResponse.ok(shortCodeService.getUniqueUuidList(request.getParam()));
    }

    @PostMapping("/getPrivacyAgreement")
    @ApiOperation(value = "获取集团隐私协议", notes = "获取集团隐私协议")
    public DataResponse<String> getPrivacyAgreement() {
        Corporation corporation = corporationService.getCorporationByCorporationCode(QfContextHolder.getContext().getCorporationCode());
        if (corporation == null){
            throw new BusinessException("集团不存在");
        }
        return DataResponse.ok(corporation.getPCprivacyAgreement());
    }

    @PostMapping("/incrementAddToDict")
    @ApiOperation(value = "增量更新集团初始参数", notes = "增量更新集团初始参数")
    public DataResponse incrementAddToDict(){
        corporationService.incrementAddToDict();
        return DataResponse.ok();
    }

    @PostMapping("/getWebsiteIncludeInfo")
    @ApiOperation(value = "获取网站收录信息", notes = "获取网站收录信息")
    public DataResponse getWebsiteIncludeInfo(@Valid @RequestBody DataRequest<WebsiteIncludeInfoReqDto> request) {
        request.getParam().setCityCode(QfContextHolder.getContext().getCityCode());
        WebsiteIncludeInfoDto websiteIncludeInfoDto;
        try {
            websiteIncludeInfoDto = corporationService.getWebsiteIncludeInfo(request.getParam());
            websiteIncludeInfoDto.setReqDto(request.getParam());
            log.info("获取网站收录信息，集团_城市:{}入参:{}，出参：{}", QfContextHolder.getContext().getCorporationCode() + "——" + QfContextHolder.getContext().getCityCode(), JSON.toJSONString(request), JSON.toJSONString(websiteIncludeInfoDto));
            return DataResponse.ok(websiteIncludeInfoDto != null ? websiteIncludeInfoDto : new WebsiteIncludeInfoDto());
        } catch (Throwable e) {
            log.error("获取网站收录信息异常，集团_城市:{}，入参:{}", QfContextHolder.getContext().getCorporationCode() + "——" + QfContextHolder.getContext().getCityCode(), JSON.toJSONString(request), e);
            websiteIncludeInfoDto = new WebsiteIncludeInfoDto();
            websiteIncludeInfoDto.setReqDto(request.getParam());
            return new DataResponse(ResponseCode.SUCC.getStatus(), e.getMessage(), websiteIncludeInfoDto);
        }
    }

    @PostMapping("/getCorporationCode")
    @ApiOperation(value = "从上下文中获取集团code", notes = "从上下文中获取集团code")
    public DataResponse<String> getCorporationCode(HttpServletRequest request) {
        return DataResponse.ok(QfContextHolder.getContext().getCorporationCode());
    }
}

